/*
 * Optimizer.h
 *
 *      Author: Jerome RD Soine and Christoph A Brand
 *      Institution: Schwarz goup, Institute for Theoretical Physics, Heidelberg University, Germany
 */

#ifndef OPTIMIZER_H_
#define OPTIMIZER_H_

#include <vector>
#include <string>
#include "CellModel.h"
#include "SubstrateModel.h"
#include "worker/WorkerManager.h"
#include "Comparator.h"

using namespace std;

/*!
 * 	\brief Super class for optimization procedures addressing the optimization of CellModel parameters
 * 	with respect to experimental substrate displacements.
 *
 * 	This class is the base class for implementations of optimization procedures. It uses a CellModel, a SubstrateModel, and
 * 	a Comparator object. Common properties of optimization procedures are defined here.
 */

class Optimizer {
protected:
	/*!
	 * CellModel on which the optimization is based.
	 */
	CellModel * cell_model;
	/*!
	 * SubstrateModel on which the optimization is based.
	 */
	SubstrateModel * substrate_model;
	/*!
	 * Used to compare model and experimental displacement fields.
	 */
	Comparator * comparator;
	/*!
	 * Number of threads that shall be for the calculation (we recommend here the # of cores). Must be at least 2.
	 */
	unsigned int n_threads;
	/*!
	 * Number of maximal iterations used by iterative optimization procedures.
	 */
	unsigned int n_iterations;
	/*!
	 * Desired tolerance of the optimization result.
	 */
	double tolerance;
	/*!
	 * Desired gradient spacing base in case of a gradient method like ConjugatedGradient. gradient_spacing_scaling defines dx relative to this base value.
	 */
	double gradient_spacing_base;
	/*!
	 * Defines dx_i relative to gradient_spacing_base
	 */
	vector<double> gradient_spacing_scaling;
	/*!
	 * Pointer to the WorkerManager used. A instance is initialized by the constructor of this class.
	 */
	WorkerManager * worker_manager;
	/*!
	 * Defines the solution folder in order to solve intermediate solutions while iterating.
	 */
	string solution_folder;
	/*!
	 * Vector object that holds the current solution.
	 */
	vector<double> solution;
	/*!
	 * Can be implemented to write output files about the current state of optimization. Is called between two optimization iteration steps.
	 */
	virtual void write_current_state(unsigned int step_index) {};

public:
	/*!
	 * Object Constructor. All object parameters are assigned by constructor arguments.
	 */
	Optimizer(CellModel * CELL_MODEL, SubstrateModel * SUBSTRATE_MODEL, Comparator * COMPARATOR, string SOLUTION_FOLDER, unsigned int N_ITERATIONS, unsigned int N_THREADS, double TOLERANCE, double GRADIENT_SPACING_BASE);
	/*!
	 * Object Deconstructor.
	 */
	virtual ~Optimizer() { delete cell_model; delete substrate_model; };
	/*!
	 * Virtual function that needs to be implemented by derived optimization objects.
	 */
	virtual void run() = 0;
	/*!
	 * Returns current solution vector.
	 */
	vector<double> get_solution() {return solution;};
	/*!
	 * Returns gradient at current position in parameter space.
	 */
	vector<double> gradient(vector<double> parameters);
	/*!
	 * Returns optimization results of a line minimization along a direction outgoing from a given
	 * start position.
	 */
	vector<double> line_minimization(vector<double> start_pos, vector<double> direction);
	/*!
	 * Returns the boundaries [min,max] for a bracketed minimum along a direction in paramters space starting at
	 * start position.
	 */
	vector<double> bracket_line_minimum(vector<double> start_pos, vector<double> direction, vector<double> & seed);
	/*!
	 * Set gradient_spacing_scaling, which defines the dx_i relative to gradient_spacing_base
	 */
	void set_gradient_spacing_scaling(vector<double> GRADIENT_SPACING_SCALING);
};


#endif /* OPTIMIZER_H_ */
